#include "upgradetool.h"


UpgradeTool::UpgradeTool(QWidget *parent) :
    QMainWindow(parent),
    ymodemFileTransmit(new YmodemFileTransmit),
    ymodemFileReceive(new YmodemFileReceive),
    ui(new Ui::UpgradeTool)
{
    ui->setupUi(this);
    this->setFixedSize(this->width(), this->height()); // 固定窗口

    serialPort = new QSerialPort();
    led_timer = new QTimer();
    serial_timer = new QTimer();

    // 寻找串口的端口号
    Find_SerialPort(); 

    transmitButtonStatus = false;
    receiveButtonStatus = false;
    // 升级按键
    ui->btn_start_update->setEnabled(true); // 使能
    ui->btn_stop_update->setEnabled(false); // 不使能

    // 绑定信号和槽函数
    connect(led_timer, SIGNAL(timeout()), this, SLOT(led_timer_irq()));
    connect(serial_timer, SIGNAL(timeout()), this, SLOT(ss_timer_irq()));
    connect(ymodemFileTransmit, SIGNAL(transmitProgress(int)), this, SLOT(transmitProgress(int))); // 进度条
    connect(ymodemFileTransmit, SIGNAL(transmitStatus(YmodemFileTransmit::Status)), this, SLOT(transmitStatus(YmodemFileTransmit::Status))); // 当前升级状态

    led_timer->start(1); // 定义周期1ms
}

UpgradeTool::~UpgradeTool()
{
    delete ui;
}

/**
 * @brief 寻找串口的端口号
 * 
 */
void UpgradeTool::Find_SerialPort()
{
    const auto infos = QSerialPortInfo::availablePorts();
    ui->lab_img_find_serial->setPixmap(QPixmap(":/new/prefix/img/green.png"));
    ui->cbx_com_name->clear();

    QTimer *time = new QTimer();
    time->start(500);

    for(const QSerialPortInfo &info:infos)
    {
        QSerialPort serial;
        serial.setPort(info);
        if(serial.open(QIODevice::ReadWrite))
        {
            ui->cbx_com_name->addItem(info.portName()+" "+info.description());
            serial.close();
        }
    }
    find_led_timer = 200;
    int max_len = 0;
    for(int idx=0; idx < ui->cbx_com_name->count(); idx++)
    {
        if(max_len < ui->cbx_com_name->itemText(idx).length())
            max_len = ui->cbx_com_name->itemText(idx).length();
    }
    int pt_val = this->font().pointSize();
    const_cast<QAbstractItemView*>(ui->cbx_com_name->view())->setMinimumWidth(max_len*pt_val);
}

/**
 * @brief 搜索串口按键前面的led定时器超时回调函数
 * 
 */
void UpgradeTool::led_timer_irq()
{
    if(find_led_timer > 0)
    {
        find_led_timer--;
        if(find_led_timer == 0)
        {
            ui->lab_img_find_serial->setPixmap(QPixmap(":/new/prefix/img/red.png"));
        }
    }
}

void UpgradeTool::ss_timer_irq()
{
    QByteArray array;
    array[0] = 0x55;
    array[1] = static_cast<char>(0xAA);

    if(serialPort->isOpen() == false)
    {
        ui->tx_firmware_msg->append("-->[error]检查串口是否被打开");
        if(serial_timer->isActive())
        {
            serial_timer->stop();
        }
        return ;
    }
    else
    {
        serialPort->write(array);
    }
}


/**
 * @brief 搜索串口按键 按下信号 的 回调函数
 * 
 */
void UpgradeTool::on_btn_find_seriaport_clicked()
{
    Find_SerialPort();
}

/**
 * @brief 打开串口按键 按下信号 的 回调函数
 * 
 */
void UpgradeTool::on_btn_open_port_clicked()
{
    QString ComName = ui->cbx_com_name->currentText().mid(0, ui->cbx_com_name->currentText().indexOf(' '));

    if(ui->btn_open_port->text() == QObject::tr("打开串口"))
    {
        serialPort->setPortName(ComName);
        if(serialPort->open(QIODevice::ReadWrite))
        {
            // 设置串口参数
            serialPort->setBaudRate(ui->cbx_bandrate->currentText().toInt());
            serialPort->setStopBits(to_convert_stopbit(ui->cbx_stopbit->currentText()));
            serialPort->setDataBits(to_convert_databit(ui->cbx_databit->currentText()));
            serialPort->setParity(to_convert_paritybit(ui->cbx_paritybit->currentText()));
            // 改变按钮显示
            ui->btn_open_port->setText(QObject::tr("关闭串口"));
            // 禁用部分控件
            ui->cbx_bandrate->setEnabled(false);
            ui->cbx_stopbit->setEnabled(false);
            ui->cbx_databit->setEnabled(false);
            ui->cbx_paritybit->setEnabled(false);
            ui->cbx_com_name->setEnabled(false);
            ui->btn_find_seriaport->setEnabled(false);
            // 改变LED灯
            ui->lab_img_openport->setPixmap(QPixmap(":/new/prefix/img/green.png"));

            setstatemsg("color:green;",u8"打开串口:"+ComName+u8",波特率:"+ui->cbx_bandrate->currentText());
            // 接收数据槽函数
            connect(serialPort, &QSerialPort::readyRead, this, &UpgradeTool::ReadData);
        }
        else {
            QMessageBox::critical(this, QObject::tr("Error"), serialPort->errorString());
        }
    }
    else
    {
        // 改变LED灯
        ui->lab_img_openport->setPixmap(QPixmap(":/new/prefix/img/red.png"));
        // 改变按钮显示
        ui->btn_open_port->setText(QObject::tr(u8"打开串口"));
        // 禁用部分控件
        ui->cbx_bandrate->setEnabled(true);
        ui->cbx_stopbit->setEnabled(true);
        ui->cbx_databit->setEnabled(true);
        ui->cbx_paritybit->setEnabled(true);
        ui->cbx_com_name->setEnabled(true);
        ui->btn_find_seriaport->setEnabled(true);

        if(serial_timer->isActive())
        {
            serial_timer->stop();
        }
        // 关闭串口
        if(serialPort->isOpen() == true)
            serialPort->close();
        setstatemsg("color:red;",u8" 串口"+ComName+u8"关闭");
    }
}

/**
 * @brief 浏览按键 按下信号的 回调函数
 * 
 */
void UpgradeTool::on_transmitBrowse_clicked()
{
    ui->transmitPath->setText(QFileDialog::getOpenFileName(this, u8"选择目录", ".", u8"任意文件 (*.bin)"));
}


void UpgradeTool::ReadData()
{
    QByteArray buf;
    // 读取串口接收数据
    buf = serialPort->readAll();

    if(!buf.isEmpty())
    {
        if(buf[0] == 'C' || buf[0] == 'c')
        {
            ui->tx_firmware_msg->append("-->[info]正在升级...");
            serial_timer->stop();
            disconnect(serialPort, &QSerialPort::readyRead, this, &UpgradeTool::ReadData);// 连接固件升级的槽函数
            
            on_transmitButton_clicked();
        }
    }
    buf.clear();
}

void UpgradeTool::on_btn_start_update_clicked()
{
    if(!(ui->transmitPath->text().isEmpty())&&(ui->btn_open_port->text() == "关闭串口"))
    {
        if(serialPort->isOpen() == false)
        {
            if(serialPort->open(QIODevice::ReadWrite))
            {
                serialPort->setBaudRate(ui->cbx_bandrate->currentText().toInt());
                serialPort->setStopBits(to_convert_stopbit(ui->cbx_stopbit->currentText()));
                serialPort->setDataBits(to_convert_databit(ui->cbx_databit->currentText()));
                serialPort->setParity(to_convert_paritybit(ui->cbx_paritybit->currentText()));

                ui->btn_open_port->setText(QObject::tr("关闭串口"));
                ui->cbx_bandrate->setEnabled(false);
                ui->cbx_stopbit->setEnabled(false);
                ui->cbx_databit->setEnabled(false);
                ui->cbx_paritybit->setEnabled(false);
                ui->cbx_com_name->setEnabled(false);
                ui->btn_find_seriaport->setEnabled(false);
                
                connect(serialPort, &QSerialPort::readyRead, this, &UpgradeTool::ReadData);
            }
        }

        serial_timer->start(100);
        ui->btn_start_update->setEnabled(false);
        ui->btn_stop_update->setEnabled(true);
        ui->transmitBrowse->setEnabled(false);
    }
    else
    {
        qDebug() << "================file path error!\r\n";
    }
}

void UpgradeTool::on_btn_stop_update_clicked()
{
    if(serial_timer->isActive())
    {
        serial_timer->stop();
    }
    transmitButtonStatus = false;
    ymodemFileTransmit->stopTransmit();
    ui->btn_start_update->setEnabled(true);
    ui->btn_stop_update->setEnabled(false);
}


void UpgradeTool::on_transmitButton_clicked()
{
    if(transmitButtonStatus == false)
    {
        serialPort->close();
        // 设置文件路径
        ymodemFileTransmit->setFileName(ui->transmitPath->text());
        ymodemFileTransmit->setPort(this->serialPort);
        // 开始传输
        if(ymodemFileTransmit->startTransmit() == true)
        {
            transmitButtonStatus = true;
            QByteArray array;
            array[0] = 0x55;
            array[1] = static_cast<char>(0xAA);
            serialPort->write(array);
        }
        else
        {
            QMessageBox::warning(this, u8"失败", u8"文件发送失败！", u8"关闭");
        }
    }
    else
    {
        ymodemFileTransmit->stopTransmit();
    }
}



void UpgradeTool::transmitStatus(Ymodem::Status status)
{
    switch(status)
    {
    case YmodemFileTransmit::StatusEstablish:
    {
        ui->tx_firmware_msg->append("-->[info]握手成功...");
        break;
    }

    case YmodemFileTransmit::StatusTransmit:
    {
        ui->tx_firmware_msg->append("-->[info]正在发送...");
        break;
    }

    case YmodemFileTransmit::StatusFinish:
    {
        transmitButtonStatus = false;
        ui->tx_firmware_msg->append("-->[info]固件升级成功");
        ui->transmitBrowse->setEnabled(true);
        ui->btn_start_update->setEnabled(true);
        ui->btn_stop_update->setEnabled(false);
        QMessageBox::warning(this, u8"成功", u8"文件发送成功！", u8"关闭");
        break;
    }

    case YmodemFileTransmit::StatusAbort:
    {
        transmitButtonStatus = false;
        ui->tx_firmware_msg->append("-->[info]升级被用户取消");
        ui->transmitBrowse->setEnabled(true);
        QMessageBox::warning(this, u8"失败", u8"文件发送失败！", u8"关闭");

        break;
    }

    case YmodemFileTransmit::StatusTimeout:
    {
        transmitButtonStatus = false;
        ui->tx_firmware_msg->append("-->[info] 和设备链接超时");
        ui->transmitBrowse->setEnabled(true);
        QMessageBox::warning(this, u8"失败", u8"文件发送失败！", u8"关闭");
        break;
    }

    default:
    {
        transmitButtonStatus = false;
        ui->tx_firmware_msg->append("-->[info ] 未知的异常出现");
        ui->transmitBrowse->setEnabled(true);

        QMessageBox::warning(this, u8"失败", u8"文件发送失败！", u8"关闭");
    }
    }
}

void UpgradeTool::transmitProgress(int progress)
{
    ui->transmitProgress->setValue(progress);
}

QSerialPort::StopBits UpgradeTool::to_convert_stopbit(QString bit)
{
    if(bit == tr("1"))
        return QSerialPort::OneStop;
    else if (bit == tr("1.5"))
        return QSerialPort::OneAndHalfStop;
    else if (bit == tr("2"))
        return QSerialPort::TwoStop;
    return QSerialPort::OneStop;
}

QSerialPort::DataBits  UpgradeTool::to_convert_databit(QString  bit)
{
    if(bit == tr("8"))
        return QSerialPort::Data8;
    if(bit == tr("7"))
        return QSerialPort::Data7;
    if(bit == tr("6"))
        return QSerialPort::Data6;
    if(bit == tr("5"))
        return QSerialPort::Data5;
    return QSerialPort::Data8;
}

QSerialPort::Parity  UpgradeTool::to_convert_paritybit(QString  bit)
{
    if(bit == tr("None"))
        return QSerialPort::NoParity;
    if(bit == tr("Odd"))
        return QSerialPort::OddParity;
    if(bit == tr("Even"))
        return QSerialPort::EvenParity;
    return QSerialPort::NoParity;
}


